package com.rwcw.admin.config.token;

import cn.hutool.core.util.StrUtil;
import com.rwcw.admin.util.RedisUtil;
import com.rwcw.admin.util.RequestUtil;
import com.rwcw.admin.vo.TokenUser;
import org.springframework.stereotype.Component;
import org.springframework.web.context.request.RequestContextHolder;
import org.springframework.web.context.request.ServletRequestAttributes;

import javax.annotation.Resource;
import javax.servlet.http.HttpServletRequest;
import java.util.Arrays;
import java.util.Objects;
import java.util.UUID;
import java.util.concurrent.TimeUnit;

/**
 * token验证处理
 */
@Component
public class FrontTokenComponent {

    @Resource
    private RedisUtil redisUtil;

    private static final Long MILLIS_MINUTE_TEN = 20 * 60 * 1000L;

    private static final Long MILLIS_MINUTE = 60 * 1000L;

    public static final long TOKEN_EXPRESS_MINUTES = 4320; //3天

    public static final long REGISTER_TOKEN_EXPRESS_MINUTES = 3;

    //用户登token redis存储前缀
    public static final String USER_TOKEN_REDIS_KEY_PREFIX = "TOKEN_USER:";
    //用户登录token与用户手机号对照前缀
    public static final String ACCOUNT_KEY_PREFIX = "ACCOUNT_KEY_PREFIX:";
    //头部 token令牌key
    public static final String HEADER_AUTHORIZATION_KEY = "token";
    public static final String REGISTER_TOKEN_REDIS_KEY_PREFIX = "TOKEN_REGISTER:";

    // 令牌有效期
    private static final int expireTime = 5 * 60;

    /**
     * 删除用户身份信息
     */
    public void delLoginUser(String token) {
        if (StrUtil.isNotEmpty(token)) {
            String userKey = this.getTokenKey(token);
            this.redisUtil.delete(userKey);
        }
    }

    /**
     * 创建令牌
     *
     * @param tokenUser 用户信息
     * @return 令牌
     */
    public String createToken(TokenUser tokenUser) {
        // 下线用户
        this.forcedOffline(tokenUser.getAccount());
        String token = UUID.randomUUID().toString().replace("-", "");
        //用户token
        this.redisUtil.set(this.getTokenKey(token), tokenUser.getUserId(), TOKEN_EXPRESS_MINUTES, TimeUnit.MINUTES);
        return token;
    }

    /**
     * @param account 用户账号
     * @return tokenKey
     */
    private String getAccountTokenKey(String account) {
        return ACCOUNT_KEY_PREFIX + account;
    }


    /**
     * 创建注册令牌
     *
     * @return 令牌
     */
    public String createRegisterToken(String mobile) {
        String token = UUID.randomUUID().toString().replace("-", "");
        this.redisUtil.set(this.getRegisterTokenKey(token), mobile, REGISTER_TOKEN_EXPRESS_MINUTES,
                TimeUnit.MINUTES);
        return token;
    }


    /**
     * 获取请求token
     *
     * @param request HttpServletRequest
     * @return token
     */
    public String getToken(HttpServletRequest request) {
        String token = request.getHeader(HEADER_AUTHORIZATION_KEY);
        if (StrUtil.isNotEmpty(token) && token.startsWith(USER_TOKEN_REDIS_KEY_PREFIX)) {
            token = token.replace(USER_TOKEN_REDIS_KEY_PREFIX, "");
        }
        return token;
    }

    /**
     * 验证非Header传过来的token
     *
     */
    public String getRequestToken(String token) {
        if (StrUtil.isNotEmpty(token) && token.startsWith(USER_TOKEN_REDIS_KEY_PREFIX)) {
            token = token.replace(USER_TOKEN_REDIS_KEY_PREFIX, "");
        }
        return token;
    }

    private String getTokenKey(String uuid) {
        return USER_TOKEN_REDIS_KEY_PREFIX + uuid;
    }

    private String getRegisterTokenKey(String uuid) {
        return REGISTER_TOKEN_REDIS_KEY_PREFIX + uuid;
    }

    /**
     * 推出登录
     *
     * @param request HttpServletRequest
     */
    public void logout(HttpServletRequest request) {
        String token = this.getToken(request);
        this.delLoginUser(token);
    }

    /**
     * 获取当前登录用户id
     */
    public Integer getUserId() {
        HttpServletRequest request = ((ServletRequestAttributes) Objects.requireNonNull(
                RequestContextHolder.getRequestAttributes())).getRequest();
        String token = this.getToken(request);
        if (StrUtil.isEmpty(token)) {
            return null;
        }
        return this.redisUtil.get(this.getTokenKey(token));
    }

    /**
     * 获取当前登录用户id
     */
    public String getUid() {
        HttpServletRequest request = ((ServletRequestAttributes) Objects.requireNonNull(
                RequestContextHolder.getRequestAttributes())).getRequest();
        String token = this.getToken(request);
        if (StrUtil.isEmpty(token)) {
            return null;
        }
        return this.redisUtil.get(this.getTokenKey(token));
    }

    /**
     * 获取当前登录用户id
     */
    public String getUidByRequest(String requestToken) {

        String token = this.getRequestToken(requestToken);
        if (StrUtil.isEmpty(token)) {
            return null;
        }
        return this.redisUtil.get(this.getTokenKey(token));
    }

    //路由在此处，则返回true，无论用户是否登录都可以访问
    public boolean checkRouter(String uri) {
        String[] routerList = {
                "admin/test",
                "admin/login",
                "admin/getCode",
        };
        return Arrays.asList(routerList).contains(uri);
    }

    public Boolean check(String token, HttpServletRequest request) {

        try {
            boolean exists = this.redisUtil.exists(this.getTokenKey(token));
            if (exists) {
                String uid = this.redisUtil.get(this.getTokenKey(token))+"";
                this.redisUtil.set(this.getTokenKey(token), uid, TOKEN_EXPRESS_MINUTES, TimeUnit.MINUTES);
            } else {
                //判断路由，部分路由不管用户是否登录/token过期都可以访问
                exists = this.checkRouter(RequestUtil.getUri(request));
            }
            return exists;
        } catch (Exception e) {
            return false;
        }
    }

    public void forcedOffline(String account) {
        String accountTokenKey = this.getAccountTokenKey(account);
        String token = this.redisUtil.get(accountTokenKey);

        if (token != null) {
            this.redisUtil.delete(this.getTokenKey(token));
            this.redisUtil.delete(accountTokenKey);
        }
    }
}
